JavaScript

text::Html5

text::CSS3

ajax请求

Ajax(Asynchronous JavaScript and XML),直译为“异步的JavaScript与XML技术”,与传统的Web应用相比,Ajax通过浏览器与服务器进行少量的数据交换就可以实现网页的异步更新,在不重新加载整个网页的情况下,即可对网页进行更新。

ECMAScript 6 入门 - 《阮一峰 ECMAScript 6 (ES6) 标准入门教程 第三版》 - 书栈网 · BookStack


一、JS基础

1 简介

面向对象的解释性语言,主要目的是验证发往服务器的数据,增加 Web 互动,弱类型语言。

语句从上到下执行,一行一个语句,语句后带分号,表达式不带分号。

JS组成 解释
ECMAScript(基础语法) JavaScript的核心语法。描述了该语言的语法和基本对象
DOM(文档对象模型) 描述了处理网页内容的方法和接口
BOM(浏览器对象模型) 描述了与浏览器进行交互的方法和接口

2 基本用法

JS需要和HTML一起使用才有效果,我们可以通动直接或间接的方式将Js代码嵌入在HTML页面中。

我们可以将JavaScript代码放在html文件中任何位置,但是我们一般放在网页的head或者body部分。由于页面的加载方式是从上往下依次加载的,而这个对我们放置的js代码运行是有影响的。

  1. 放在<head>部分,最常用的方式是在页面中head部分放置<script>元素,浏览器解析head部分就会执行这个代码,然后才解析页面的其余部分。

  2. 放在<body>部分,JavaScript代码在网页读取到该语句的时候就会执行。

  3. 放在<body>标签后(推荐)。此时页面已经加载完成。再加载JavaScript代码时就比较稳定,不会出现由于标签未执行而导致空异常等报错。

调试:直接在界面加断点。

<!--行内JS:写在标签内部的js代码-->
<button type="button" onclick="alert('Hello World')">按一下</button>

<!--内部JS:定义在script标签内部的js代码-->
<script type="text/javascript"> ... </script>

<!--外部JS单独的js文件,在HTML中通过script标签引入-->
<script src="js/*.js" type="text/javascript" charset="UTF-8"></script>

二、基本语法

1 输出

// 界面输出
alert();
// 控制台输出
console.log();
// 打印中不要有加号,它会当做字符串拼接而非两个值

// 点击事件
onclick="code";

2 注释

同C语言。
//
/**/
<!-- -->

3 变量

let和var的区别:

  • let只能在代码块内使用
  • var可以重复声明,let不行
  • var会变量提升,let不会
// 任意类型,声明未赋值会返回undefine
var str = "";

// 变量提升:所有声明代码会提升到最前面。
console.log(uname);
var uname = "zhang";
// 等于如下代码
var uname;
console.log(uname);
uname = "zhang";
// 只有用 var 声明的代码才会变量提升


// 不用 var 也可直接赋值
up = "123";

// let允许你声明一个作用域被限制在块级中的变量、语句或者表达式。在Function中局部变量推荐使用let变量,避免变量名冲突。
// 属于定义了同一个x
function func{
var x;
if{ var x; }
}
// 属于定义了不同的x
function func{
let x;
if{ let x; }
}

// 常量定义和赋值(定义时必须赋值,值不可修改,否则会报异常)
const PI = 3.14159;
// 常量赋值引用类型(不可以改引用对象,但是可以改引用对象中的值)
const p = this.node.position;
p.x += 1;
// ES6明确规定,代码块内如果存在let或者const,代码块会对这些命令声明的变量从块的开始就形成一个封闭作用域。代码块内,在声明变量PI之前使用它会报错。

// 报错
var PI = "3.1415926";
if(true)
{
console.log(PI);
let PI;
}
// 输出undefined
var PI = "3.1415926";
if(true)
{
let PI;
console.log(PI);
}

4 数据类型

值类型:

  • Number:所有数字是浮点存储,但若是整型,浮点会自动转化成整型(例如3.0转化为3)
  • String
  • Boolean
  • undefined:function中未传参参为undefined,无返回值返回undefined
  • null:typeof测试object字符串返回值,undefined与null等值,bool测试为true

引用类型:

  • object:像字典集合
  • array
  • function
// typeof使用,判断类型
typeof var_name;

// 判断是否是数字
isNaN(num);
// 将字符串转化为整形,从头开始判断直到不为数字,首字符不为则直接返回 NaN
parseInt('str');
// 将字符串转化为浮点型,从头开始判断直到不为浮点规则(如22.33.4 = 22.33),首字符不为则直接返回 NaN
parseFloat('str');

// 数字转字符串,null 和 undefined 不能转
int/float.toString();
// 保留 num 位小数
int/float.toFixed(num);

// 构造数字,布尔,字符串
Number();
Boolean();
String();

// 获得值
variable.value();
label_name[.label_name].value();
// ES6新增:Symbol(功能类型一种标识唯一性的ID)

// 新建(参数是描述信息)
let s1 = Symbol();
let s2 = Symbol('another symbol');
let s3 = Symbol('another symbol');

// 唯一性证明(返回的是false)
console.log(s2 === s3);

// 使用场景1:作为类的属性值(使用for无法获取,可以相当于私有属性使用)
const PROP_NAME = Symbol();
const PROP_AGE = Symbol();

let obj = {
[PROP_NAME]:"一斤鸭梨";
}
obj[PROP_AGE] = 12;
console.log(obj[PROP_NAME]);
console.log(obj[PROP_AGE]);

// 仅获得类的“公有属性”
console.log(Object.keys(obj));
// 仅获得类的“私有属性”
console.log(Object.getOwnPropertySymbols(obj));
// 获得所有属性
console.log(Reflect.ownKeys(obj));

// 使用场景2:使用Symbol来替代常量
const TYPE_AUDIO = 'AUDIO';
const TYPE_AUDIO = Symbol();

5 运算符

同C语言。

不同:

\==:判断相等,比较值
===:判断全等,比较值和类型

6 选择语句

if 同 C语言。

switch 同C语言。

7 循环语句

while同C语言。

do…while同C语言。

for同C语言。

8 捕获异常

try {
// 可能会抛出异常的代码
let result = someFunction();
console.log(result);
}
catch (error) {
// 捕获异常并进行处理
console.error("An error occurred:", error);
}
finally {
// 最终会执行的代码
console.log("The try-catch block has finished executing.");
}

三、数组

1 定义

//同 python 的 list

//隐式创建
var arr = [value_1,value_2,value_3];
//直接实例化
var arr = new Array(value_1,value_2,value_3);
//创建数组并指定长度
var arr = new Array(size);

//获得 / 设置长度
arr.length;
//索引获取 / 设置,不会越界,越界返回 undefined
arr[num];
//设置属性,key:value,会新增属性,不会改变数组长度
arr[key];

2 数组遍历

数组在使用的时候建议大家规矩来用。在存放数据时,从下标0开始顺序的存放数组元素。如果下标:

  1. 为非负整数(包括整数字符串)︰自动从0开始,不存在添加undefined。
  2. 为负数、小数、非数字符串:这些内容不计算在长度内,当成”属性”处理,相当于自定义属性。

数组非常灵活,使用数组元素:

  1. index:非负整数(包括整数字符串)使用arr.indexarr[ index ]

  2. index:负数、小数、非数字字符串使用arr[key]

//for -->不遍历属性
for(var i=0;i<arr.length;i++) {}

//for in -->不遍历索引中的 undefined
for(var index in arr) {}

//foreach -->不遍历属性和索引中的 undefined
//完全一致,无需该函数元素索引名
function func(element,index) {}
arr.foreach(func( element,index)) {}

3 排序函数

函数 排序依据 排序规则 ”键值对“是否改变
sort() 元素值 升序
rsort() 元素值 降序
asort() 元素值 升序
arort() 元素值 降序
ksort() 索引值 升序
krsort() 索引值 降序
natsort() 元素值 升序
natcasesort() 元素值 升序
shuffle() 元素值 随机乱序

4 解构赋值

ES6新特性,优点如下:

  • 解构赋值是对赋值运算符的扩展。
  • 他是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。
  • 在代码书写上简洁且易读,语义更加清晰明了;也方便了复杂对象中数据字段获取。
// 数组的解构赋值
// 基本用法(a=1,b=2,c=3)
let [a,b,c] = [1,2,3];

// 嵌套赋值(a=1,b=2,c=3)
let [a,[[b],c]] = [1,[[2],3]];

// 忽略值(a=1,b=3)
let [a,,b] = [1,2,3]

// 剩余运算符(a=1,b=[2,3])
let [a, ...b] = [1,2,3];

// 默认值
let [a = 3, b = a] = []; // a=b=3
let [a = 3, b ] = [4,6] // a=4,b=6
// 结果未定义存在默认值,返回默认(a=2)
let [a = 2] = [undefined];

// 空值赋undefined(a=1,b=undefined)
let [a,b] = [1];

// 字符串解构(a='H',b='e',以此类推)
let [a,b,c,d,e] = 'Hello';
// 对象解构
// 基本用法
let { foo, bar } = { foo:'aaa', bar 'bbb'};
let { foo : bar } = { foo : 'ddd'};

// 可嵌套(x='hello',y='world')
let obj = {p : ['hello', {y: 'world'}]};
let {p: [x, {y}]} = obj;

// 可忽略(x='hello')
let obj = {p : ['hello', {y: 'world'}]};
let {p: [x, { }]} = obj;

// 不完全解构(x=undefined,y='world')
let obj = {p: [{y: 'world'}]};
let {p: [{y},x]} = obj;

// 剩余运算符(a=10,b=20,rest={c:30,d:40})
let {a,b, ...rest} = {a:10, b:20, c:30, d:40};

// 结构默认值
//(a=3,b=5)
let {a = 10, b = 5} = {a: 3};
//(aa=3,bb=5)
let {a: aa = 10, b: bb = 5} = {a: 3};

四、函数

1 定义

使用函数声明语句声明函数具有函数名提升的效果。

JS没有函数重载,新定义的同名函数会覆盖原函数。

参数:函数运行的时候,有时需要提供外部数据,不同的外部数据会得到不同的结果,这种外部数据就叫参数,定义时的参数称为形参,调用时的参数称为实参。

  1. 实参可以省略,那么对应形参为undefined。
  2. 若函数形参同名(一般不会这么干)︰在使用时以最后一个值为准。
  3. 可以给参数默认值:当参数为特殊值时,可以赋予默认值。
  4. 参数为值传递,传递副本;引用传递时传递地址,操作的是同一个对象。

变量:函数外全局变量,函数内局部变量。

  1. 同名:同名不影响。
  2. 函数内不加 var 修饰符则为全局变量。
// 函数声明语句(命名函数)
function name ( [value] ) {};

// 函数定义表达式,匿名函数,将函数赋给一个变量
var name = function( [value] ){};

// Function构造函数,前面任意多的value是参数,最后一个参数是函数主体
var name = new Function( value );
// 下面两个语句意义一样
var add = new Function('x','y','return (x + y)');
function add (x,y) {return (x + y);}


// 自执行函数(声明后立刻调用且只调用一次)
// 写法1:(func)(value)
(function(n1,n2){
console.log(n1,n2);
})(10,100);

// 写法2:(func(value))
(function(n1,n2){
console.log(n1,n2);
}(10,100));
 // 返回值强制转化成bool的技巧(第一个!会将非bool值转化成bool值,第二个!取反,获得正确值)
is_action_pressed(k) {
return !!this._pressd_map[k];
}

2 计时函数

// 间隔指定的毫秒数不停地执行指定的代码(重复执行)。
setInterval("fun()",delay);
// 在指定的毫秒数后执行指定代码(一次性执行)。
setTimeout("fun()",delay);

// 停止 setInterval() 方法执行的函数代码。
clearInterval(index);
// 停止 setTimeOut() 方法执行的函数代码。
clearTimeout(index);

3 箭头函数

ES6标准新增的函数。

箭头函数的this:

  1. 普通函数的this指向它的调用者,如果没有调用者则默认指向window。
  2. 箭头函数体中的this对象,是定义函数时的对象,而不是使用函数时的对象。
  3. 箭头函数中的this,首先从它的父级作用域中找,如果父级作用域还是箭头函数,再往上找,如此直至找到this的指向。
// 参数=>函数体
x => x + x;
var f = x => x * x;

// 无参或多个参数要用括号括起
let f = (a,b) => {
let result = a + b;
return result;
}
f(1,2);

// 返回对象(返回值要用括号包起,否则会报错)
let f = (id,name) => ({id:id ,name:name});
f(1,'Lili');
// this案例
var str = "windows";

const obj_1 = {
str:"obj_1",
nativeFn : function(){
console.log("当前作用于this:",this.str);
return function(){
console.log("原生函数this:",this.str);
}
},
arrowFn : function(){
console.log("当前作用于this:",this.str);
return () => {
console.log("箭头函数this:",this.str);
}
}
};

const obj_2 = {
str:"obj_2"
}
var nativeFn = obj_1.nativeFn();
var arrowFn = obj_1.arrowFn();

nativeFn();
arrowFn();
console.log("下面改变调用者");
nativeFn.call(obj_2);
arrowFn.call(obj_2);

五、对象

自定义对象前的对象为内置对象。

1 with

// with语句中的变量都会默认指向with后面所包含的对象。
<form name="myform"></form>
with(document.myform)
{
var username = username.value;
}

2 String

字符串对象

属性

// 返回字符串的长度
str.length

方法

// 返回指定位置处的字符,也可以直接用索引获得。
str.charAt(idx);
// 返回指定子字符串的位置,从左到右。找不到返回-1(起始位置)。
str.indexOf(chr,start);
// 反向检索
lastIndexOf(chr,start);

// 在字符串中用一些字符替换另一些字符
replace(regexp/substr,replacement);

// 把一个字符串分割成字符串数组(同py)
split(separator,limit);

// 返回给定字符串中从m位置开始,取n个字符,如果参数n省略,则意味着取到字符串末尾。
str.substr(m,n);
// 返回给定字符串中从m位置开始,到n位置结束,如果参数n省略,则意味着取到字符串末尾。
str.substring(m, n);

// 将字符串中的字符全部转化成小写。
str.toLowerCase();
// 将字符串中的字符全部转化成大写。
str.toUpperCase();

// /n转<br />
nl2br(string);
// 除去字符串中的HTML、XML、PHP标记
strip_tags(string,[allow]);

3 Math

数学对象

// 随机数,0-1
Math.random();
// 向上取整
Math.ceil(value);
// 向下取整
Math.floor(value);
// 四舍五入
Math.round(value);
// 最大最小
Math.max(value_1,value_2);
Math.min(value_1,value_2);
// 绝对值
Math.abs(value);
// 次方
Math.pow(value,n);
// 开方
Math.sqrt(value);


// π
Math.PI;
// 正弦和反正弦(其他三角函数同理)
Math.sin(value);
Math.asin(value);

4 Date

日期对象

转换成本地时间字符串说明:

  1. getMonth():得到值:0~11 (1月~12月)
  2. setMonth():设置值:0~11
  3. toLocaleString():可根据本地时间把 Date 对象转换为字符串,并返回结果。

toLocaleString()

// B端时间。
// 通过new方法创建日期对象
var mydate=new Date();
// 获取日期(年月日时分秒)
getFullYear();
getMonth();
getDate();
getHours();
getMinutes();
getseconds();
// 设置日期
setYear();
setMonth();
setDate();
setHours();
setMinutes();
setSeconds();
// 数字转换为本地格式表示的字符串
toLoacaleString();

5 Array

数组对象

sortby

// 添加元素到最后
arr.push(value);
// 添加元素到最前
arr.unshift(value);
// 删除最后一项
arr.pop();
// 删除第一项
arr.shift();
// 删除元素
delete arr[index];

// 数组排序
arr.sort(sortby);
// sortby(升序,b-a是降序,原理同C)
function(a,b){return a-b};
// 数组翻转
arr.reverse();
// 数组转成字符串,以value分割
arr.join([value]);

// 数组元素索引
arr.indexOf(value);
// 截取(切片)数组,原数组不发生变化,[ start , end )
arr.slice(start,end);
// 剪接数组,原数组变化,从start开始切num出来,再新增元素add_1等
arr.splice(start,num,[add_1 , add_2 , ...]);
// 数组合并
arr.concat(new_arr);

6 Arguments

只在函数内定义,保存了函数的实参。

7 document

通过javascript来操作DOM元素

获取DOM属性

// 从上到下依ID获得DOM(加s获得数组)
document.getElementById(id);
document.getElementsById(id);

// Name获得,edge 12以上支持
document.getElementsByName(name);

// 依html获得,只有这个函数可以操作动态的dom
document.getElementsByTagName(tag);

// 类名获得,ie9以上支持
document.getElementsByClassName(class);

// CSS选择器获得,ie8部分支持,ie9及以上支持。
document.querySelector(选择器);
document.querySelectorAll(选择器);

// 获取对象值
dom.innerHTML;
dom.innerText;

操作DOM属性

// 对象属性
// 此种方法无法获取自定义属性
dom.html_attr='值';
// 这种方法可以改变元素的css类,从而调整外观
dom.class_Name='类名';

// 对象方法
// 获取指定dom元素的attr属性,可以获取自定义属性
dom.getAttribute('attr');
// 设置指定dom元素attr属性的值
dom.setAttribute('attr','值')
// 删除指定dom元素的attr属性
dom.removeAttribute('attr');
// 判断指定dom元素是否含有attr属性
dom.hasAttribute('attr');

操作CSS属性

// 获取CSS属性值
// 注意css属性的驼峰写法,background-color应写成backgroundColor
// obj.style.attr的方式只能获取css行内属性,而不能获取其他方式的css属性,所以应该用getComputedStyle方法来获取完整的css属性
getComputedStyle(dom).property;
getComputedStyle(dom)['property'];

// 设置CSS属性值
// 此方法只能设置行内样式,一次只能设置一个css属性
dom.style.property='new style';
// 一次可以设置多个属性。实际应用中更倾向与使用dom元素.className='类名',这个方法来改变元素的多个属性
dom.style.cssText="style";

DOM遍历

// 父节点
dom.parentNode;

// 子节点
// 获取所有子节点,包括元素节点和文本节点
dom.childNodes;
// 获取所有元素节点,不包括文本节点
dom.children;
// 第一个子节点,包括元素节点和文本节点
dom.firstChild;
// 第一个元素节点
dom.firstElementChild;
// 最后一个子节点,包括元素节点和文本节点
dom.lastChild;
// 最后一个元素节点
dom.lastElementChild;

// 注意:使用childNodes、firstChild、lastChild来操作元素节点非常麻烦,因为它们把文本节点(一般是空白节点)包括进来了,Javascript为了让我们可以快速开发,提供了新的方法,也就是只针对元素节点的操作属性,children、firstElementChild、lastElementChild。

// 兄弟节点
// 前后一个兄弟节点,包括文本节点和元素节点。
dom.previousSibling;
dom.nextSibling;
// 前后一个元素节点
dom.previousElementSibling;
dom.nextElementSibling;

动态DOM

// 要创建一个元素需要以下四步
// 1.创建元素节点
createElement('html_label');
// 2.创建文本节点
createTextNode('text_content');
// 3.把文本节点插入元素节点
parent.appendChild(B);
parent.appendChild(B,ref); //插在ref前
// 4.把组装好的元素插入到已有元素中
appendChild()

// 删除
dom.removeChild(B);
// 克隆
dom.cloneNode(bool);
// 替换
dom.replaceChild(new,old);

8 自定义对象

this:

  • 函数中使用:调用windows对象,相当于定义在全局对象上的属性。
  • 对象中使用:调用本对象的属性。
// 创建对象
// 直接赋值创建对象
var obj = {}; //空对象
var obj = { key: value, key: value, ... }

// 通过 new Object对象创建:
var obj = new Object(); //空对象

// 通过 Object 对象的 create 方法创建
var obj = Object.create(null); // 空对象
var obj = Object.create(other_obj); // 继承别的对象

// 值操作
// 直接赋值(属性在对象中可以不存在)
obj.key = value;
// 引用对象中的值
obj[key];

// 注:值不一样(中括号是引用了Symbol而点是创建了新值)
const PROP_NAME = Symbol();
const PROP_AGE = Symbol();

let obj = {
PROP_NAME:"一斤鸭梨",
PROP_AGE:12,
[PROP_NAME]:"两斤鸭梨",
[PROP_AGE]:13
}

console.log(obj.PROP_NAME);
console.log(obj.PROP_AGE);
console.log(obj[PROP_NAME]);
console.log(obj[PROP_AGE]);

9 序列化与反序列化

// 序列化对象,将对象转化为字符串
JSON.stringify(obj);
// 反序列化,将Json字符串转化为对象
JSON.parse(jsonStr);

10 Map

字典

Map和Object的区别:

  • 一个Object的键只能是字符串或者Symbols,但一个Map 的键可以是任意值。
  • Map中的键值是有序的(FIFO 原则),而添加到对象中的键则不是。
  • Map的键值对个数可以从size属性获取,而Object的键值对个数只能手动计算。
// 新建Map
let map = new Map();

// 赋值
map.set("str","The type of key is string");
map.set(obj,"The type of key is obj");

11 Set

集合

Set对象存储的值总是唯一的,所以需要判断两个值是否恒等。有几个特殊值需要特殊对待:

  • +0与-0在存储判断唯一性的时候是恒等的,所以不能重复
  • undefined与undefined是恒等的,所以不能重复
  • NaN与NaN是不恒等的,但是在Set中只能存一个,不能重复
// 新建Set
let set = new Set();

// 赋值
set.add(1);

// Array转Set
let set = new Set(["value1","value2"]);
// Set转Array
let array = [...set];

// String转Set(set = Set(4) {'H', 'e', 'l', 'o'})
let set = new Set('Hello');

// 数组去重
let set = new Set([1,2,3,3,4,4]);
let array = [...set];
// 并集
let union = new Set([...set1, ...set2]);
// 交集
let intersect = new Set([...set1].filter(x => set2.has(x)));
// 差集
let difference = new Set([...set1].filter(x => !set2.has(x)));

六、BOM

浏览器对象模型。

1 window

属性

// 表示浏览器窗口的内部大小(包括滚动条)
window.innerHeight
window.innerWidth

方法

// 打开新窗口
window.open(url)
// 关闭当前窗口
window.close()

//滚动x,y
window.scrollBy( x , y )
//滚动到x,y处
window.scrollTo( x , y )

案例

//向下滚动一页面高度
window.scrollTo(0,document.body.scrollHeight)

2 screen

浏览器窗口。

属性

// 可用的屏幕宽度
screen.availWidth
// 可用的屏幕高度(可用高度,减去任务栏)
screen.availHeight

3 location

地址栏对象。

属性

// 当前页面的url
location.href

4 history

浏览器历史对象。

方法

// 与在浏览器中点击向前按钮相同
history.forward()
// 与在浏览器点击后退按钮相同
history.back()
// 跳到浏览历史的第n项
history.go(n)
history.go(-1); // 回到上一页面

5 navigator

获得浏览器的信息。

<script>
txt = "<p>浏览器代号: " + navigator.appCodeName + "</p>";
txt+= "<p>浏览器名称: " + navigator.appName + "</p>";
txt+= "<p>浏览器版本: " + navigator.appVersion + "</p>";
txt+= "<p>启用Cookies: " + navigator.cookieEnabled + "</p>";
txt+= "<p>硬件平台: " + navigator.platform + "</p>";
txt+= "<p>用户代理: " + navigator.userAgent + "</p>";
txt+= "<p>用户代理语言: " + navigator.language + "</p>";
console.log(txt);
</script>

七、事件

1 鼠标点击事件

事件名 描述
onclick 单机鼠标左键时触发
ondbclick 双击鼠标左键时触发
onmousedown 鼠标任意键按下时触发
onmouseup 松开鼠标任意按键时触发
onmouseover 鼠标指针移动到元素上时触发
onmouseout 鼠标指针移出元素边界时触发
onmousemove 鼠标指针在元素上移动时持续触发

2 html事件

事件名 描述
onload 页面完全加载后再 window 对象上触发,图片加载完成后在其上触发
onunload 页面完全加载后再 window 对象上触发,图片卸载完成后在其上触发
onerror 脚本出错时再 window 对象上触发,图像无法载入时在其上触发
onselect 选择了文本框的某些字符或下拉列表框的某项后触发
onchange 文本框或下拉框内容改变时触发
onsubmit 表单提交时在 form 上触发
onblur 任何元素或窗口失去焦点时触发
onfocus 任何元素或窗口获得焦点时触发
onscroll 浏览器的滚动条滚动时触发
<!--点击后执行检测函数,通过可以return true来提交表单,否则return false来阻止表单提交-->
<form onsubmit="return check();"></form>

八、异步操作

1 ajax请求

Ajax(Asynchronous JavaScript and XML)是一种用于创建动态网页的技术。它通过在后台与服务器进行少量数据交换,实现页面无需刷新就能更新部分内容的效果。Ajax请求是通过JavaScript代码发起的异步HTTP请求,可以在不刷新整个页面的情况下,向服务器请求数据并更新页面的部分内容。Ajax请求通常使用XMLHttpRequest对象来实现。Ajax请求可以用于实现各种功能,如实时搜索、动态加载内容、表单验证等。

my::延迟回显

事件名 事件效果
click 鼠标点击时触发
mouseover 鼠标移入元素时触发
mouseout 鼠标移出元素时触发
mousedown 鼠标按下时触发
mouseup 鼠标松开时触发
mousemove 鼠标在元素内移动时触发
keydown 键盘按下时触发
keyup 键盘松开时触发
submit 表单提交时触发
change 表单元素的值发生改变时触发(要按回车)
input 元素内容发生改变时执行(不需要按回车)
load 页面或图片加载完成时触发
error 页面或图片加载失败时触发
// 获得元素
var read_letters = document.querySelectorAll("#read_letter");
// 创建函数
var rebound_want_read_letter = function()
{
// 获得标签
var read_letters = document.querySelectorAll("#read_letter");
// 设置绑定函数
var I_want_read_letter = function ()
{
// 创建 AJAX 请求对象
var xhr = new XMLHttpRequest();
// 发送 AJAX 请求(POST带参发送,Get可以不用构造头)
xhr.open("POST", "inc/read.php", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send("CID="+value);
// 处理 AJAX 响应
xhr.onreadystatechange = function()
{
JSON.parse(xhr.responseText); // php用json_encode()后js用该函数转换
};
// 处理 AJAX 请求错误
xhr.onerror = function() {};
}
// 多个标签若存在,依次绑定标签
if(read_letters != null)
{
read_letters.forEach(function(read_letter)
{
read_letter.addEventListener("click", I_want_read_letter);
});
}
}
// 执行函数(如果页面按钮不需要重新绑定事件可以只执行一次,不用重新绑定)
rebound_want_read_letter();

2 Promise基础

抽象表达:

1) Promise是一门新的技术(ES6规范)
2) Promise是Js中进行异步编程的新解决方案(旧方案是单纯使用回调函数)

具体表达:

  1. 从语法上来说:Promise是一个构造函数
  2. 从功能上来说:Promise对象用来封装一个异步操作并可以获取其成功/
    失败的结果值

指定回调函数的方式更加灵活:

  1. 旧的:必须在启动异步任务前指定。
  2. promise:启动异步任务=>返回promie,对象=>给promise对象绑定回调函
    数(甚至可以在异步任务结束后指定/多个)

回调地狱是指回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件。回调地狱会导致不便于阅读,不便于异常处理等问题。因为promise支持链式调用,所以可以解决回调地狱问题。

【PromiseState】

在promise对象中,存在三种状态(PromiseState):pending(待定),resolved / fulfilled(成功),rejected(失败)

promise只有下列两种转换:

  1. pending变为resolved
  2. pending变为rejected

一个promise对象只能改变一次,无论变为成功还是失败,都会有一个结果数据
成功的结果数据一般称为value,失败的结果数据一般称为reason。

【PromiseResult】

在promise对象中通过PromiseResult保存着对象成功或失败的结果,通过resolve(para)reject(para)函数传递参数来改变它的值。

// 定义
// reslove:解决,reject:拒绝。两者都是函数类型的数据
const p = new Promise((resolve, reject) =>{
setTimeout(() => {
// 随机数,1-100
let n = Math.floor(Math.random() * 100 + 1);
if(n <= 30){
resolve(); // 直接调用函数会将promise对象的状态设置成成功
}else{
reject(); // 直接调用函数会将promise对象的状态设置成失败
}
}, 1000);
});

// 调用then(参数是两个函数,1:成功时的回调,2:失败时的回调)
p.then((value) => {
alert("success!" + value);
}, (reason) => {
alert("failed!" + reason);
})
// 案例
// 异步读取文件
const handleClick = (path) => {
const p = new Promise((resolve, reject) =>{
fs.readFile(path, (err, data) =>{
if(err) reject(err);
resolve(data);
});
});

// 调用then(参数是两个函数,1:成功时的回调,2:失败时的回调)
p.then((value) => {
console.log(value.toString());
}, (reason) => {
console.log(reason.toString());
})
};

// 封装ajax请求
const handleClick = (method, path) => {
// 创建Promise
const p = new Promise((resolve, reject) => {
// 1.创建对象
const xhr = new XMLHttpRequest();
// 2.初始化
xhr.open(method, path);
// 3.发送
xhr.send();
// 4.处理响应结果
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
// 判断响应状态码2xx
if (xhr.status >= 200 && xhr.status < 300) {
// 控制台输出响应体
resolve(xhr.response);
} else {
// 控制台输出响应状态码
reject(xhr.status);
}
}
};
});

p.then((value) => {
console.log(value.toString());
}, (reason) => {
console.log(reason.toString());
});
};


3 promisify

利用promisify,可以快速地对一个方法进行封装,不需要再手动实现函数。

const fs = require('fs');
const util = require('util');

// 封装函数
const readFile = util.promisify(fs.readFile);

// 调用函数
readFile('./resource/content.txt').then(value =>{
console.log(value.toString());
})

4 Promise API

注:promise中的代码是同步代用的,不会进入到队列当中,会立即执行。

Promise构造函数:Promise(excutor){}

  1. executor函数:执行器(resolve, reject) =>{}
  2. resolve函数:内部定义成功时我们调用的函数value =>{}
  3. reject函数:内部定义失败时我们调用的函数reason =>{}
  4. 说明:executor 会在 Promise内部立即同步调用,异步操作在执行器中执行。

Promise.prototype.then方法:(onResolved, onRejected) =>{}

  1. onResoled函数:功的回调函数(value)=>{}
  2. onRejected函数:失败的回调函数(reason)=>{}
  3. 说明:指定用于得到成功value的成功回调和用于得到失败reason的失败回调
    返回一个新的promise对象

Promise.prototype.catch方法:(onRejected)=>{}

  1. onRejected函数:失败的回调函数(reason)=> {}
  2. 说明:该方法是then()的语法糖,相当于:then(undefined, onRejected)

Promise.resolve方法:(value)=>{}

  1. value: 成功的数据或promise对象,传入的promise的返回结果会影响该函数的结果。内部成功返回成功,内部失败返回失败,返回的失败会异常,要用catch()捕获处理
  2. 说明:返回一个成功/失败的promise对象

Promise.reject方法:(reason) => {}

  1. reason:失败的原因,可以是数据或promise对象
  2. 说明:返回一个失败的 promise对象,必定失败,即使传入的是成功的promise对象。返回的失败会异常,要用catch()捕获处理

Promise.all方法:(promises)=> {}

  1. promises:包含n个promise的数组
  2. 说明:返回一个新的 promise,只有所有的promise都成功才成功,只要有一个失败了就直接失败。成功返回的结果是由这些promise的成功结果构成的一个数组。失败则是返回那一个失败的promise的结果

Promise.race方法:(promises)=> {}

  1. promises:包含n个promise 的数组
  2. 说明:返回一个新的 promise,第一个完成的promise的结果状态就是最终的结果状态,无论成功失败。
// Promise构造函数
const p = new Promise((resolve, reject) =>{});

// Promise.prototype.then
p.then((value) => {}, (reason) => {});

// Promise.prototype.catch
p.catch(reason => {});

// Promise.resolve
Promise.resolve(data);

// Promise.reject
Promise.reject(data);

// Promise.all
Promise.all([p1, p2, p3]);

// Promise.race
Promise.race([p1, p2, p3]);
// Promise.race,返回的是p2的结果,因为p2先完成
let p1 = new Promise((resolve,reject)=>{
setTimeout(() => {
resolve('OK');
}, 1000);
});
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Yes');
console.log(Promise.race([p1, p2, p3]));

==promise未学==

5 promise 状态

x+1 axios 库


九、面向对象

1 class

ES6支持class关键字

// 定义类
class Point{
// 私有属性
#privateValue;

// 构造函数
constructor(x,y){
// 私有属性赋值
this.#privateValue = 1;
this.x = x;
this.y = y;
}

toString(){
return this.x + " " + this.y;
}
}

// 继承
class Child extends Father {
constructor() {
super();
}

// 属性get和set设置
class test(){
_value;

get value() {
return this.value;
}

set value(val) {
this.value = val;
}
}

2 函数嵌套

// 方法1:函数内初始化对象
function Person(name){
let obj = new Object();
obj.name = name;
obj.showName = function(){
console.log(this.name);
}
return obj;
}
let p = Person("Bob");
p.showName();

// 方法2:函数外new一个对象
function Person(name){
this.name = name;
this.showName = function(){
console.log(this.name);
}
}
let p = new Person("Bob");
p.showName();

十、其他

1 游戏

低于13kB的10个惊人的JavaScript游戏 - 知乎 (zhihu.com)